package com.itheima.stock.service.impl;

import com.google.common.collect.Lists;
import com.itheima.stock.common.StockInConfig;
import com.itheima.stock.mapper.StockBlockRtInfoMapper;
import com.itheima.stock.mapper.StockBusinessMapper;
import com.itheima.stock.mapper.StockMarketIndexInfoMapper;
import com.itheima.stock.mapper.StockRtInfoMapper;
import com.itheima.stock.pojo.StockBlockRtInfo;
import com.itheima.stock.pojo.StockMarketIndexInfo;
import com.itheima.stock.pojo.StockRtInfo;
import com.itheima.stock.service.StockTimerTaskService;
import com.itheima.stock.utils.IdWorker;
import com.itheima.stock.utils.ParserStockInfoUtil;
import lombok.extern.slf4j.Slf4j;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.web.client.RestTemplate;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * author by itheima
 *
 * @Date 2022/1/14
 * Description 定义采集股票数据的定时任务的服务接口实现
 */
@Service("stockTimerTaskService")
@Slf4j
public class StockTimerTaskServiceImpl implements StockTimerTaskService {
   //Http请求工具
    @Autowired
   private RestTemplate restTemplate;
   @Autowired
   private StockInConfig stockInConfig;
    @Autowired
    private IdWorker idWorker;
    @Autowired
    private StockMarketIndexInfoMapper stockMarketIndexInfoMapper;
    @Autowired
    private StockBusinessMapper stockBusinessMapper;
    @Autowired
    private StockRtInfoMapper stockRtInfoMapper;
    @Autowired
    private ParserStockInfoUtil  parserStockInfoUtil;
    @Autowired
    private StockBlockRtInfoMapper stockBlockRtInfoMapper;
    /**
     * 注入线程池对象
     */
    @Autowired
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;
    @Override
    public void getInnerMarketInfo() {
        //组装动态url
        /*StringUtils.join()和String.join()：可用来把字符串数组拼接成整条字符串，效果一样只是用法稍有不同，
        StringUtils要引入jar包common-lang3, String.join()是JDK8新增方法。*/
        //String.join(1,2) 参数1:表示连接的符号 参数2:表示被连接的数组(也可以是集合),或者是要连接的多个字符串
        //http://hq.sinajs.cn/list=s_sh000001,s_sz399001
        String innerUrl = stockInConfig.getMarketUrl()+String.join(",",stockInConfig.getInner());
        //直接获得响应的数据
        String result = restTemplate.getForObject(innerUrl,String.class);
        //正则表达式
        String reg = "var hq_str_(.+)=\"(.+)\";";
        Pattern pattern = Pattern.compile(reg);
        Matcher matcher = pattern.matcher(result);
        //收集大盘封装后的对象
        ArrayList<StockMarketIndexInfo> list = new ArrayList<>();
        while (matcher.find()) {
           //获取大盘的id
            String marketCode = matcher.group(1);
            System.out.println(marketCode);
            //其他信息
            String other = matcher.group(2);
            String[] others = other.split(",");
            //大盘名称
            String marketName = others[0];
            //当前点
            BigDecimal curPoint = new BigDecimal(others[1]) ;
            //当前价格
            BigDecimal currentPrice = new BigDecimal(others[2]);
            //涨跌率
            BigDecimal upDown = new BigDecimal(others[3]);
            //成交量
            Long tradeAmount = Long.valueOf(others[4]);
            //成交金额
            Long tradeVol = Long.valueOf(others[5]);
            //组装实体对象
          StockMarketIndexInfo stockMarketIndexInfo= StockMarketIndexInfo.builder()
                  .id(idWorker.nextId())
                  .markId(marketCode)
                  .curTime(new Date())
                  .markName(marketName)
                  .curPoint(curPoint)
                  .currentPrice(currentPrice)
                  .updownRate(upDown)
                  .tradeAccount(tradeAmount)
                  .tradeVolume(tradeVol)
                  .build();
            list.add(stockMarketIndexInfo);
        };
        //TODO 后续完成国内大盘批量插入的功能
    log.info("共：{}条数据,内容为：{}",list.size(),list);
        //批量插入 判断list集合是否有数据 防止空指针报错
        if (CollectionUtils.isEmpty(list)) {
            log.info("");
            return;
        }
        String curTime = DateTime.now().toString(DateTimeFormat.forPattern("yyyyMMddHHmmss"));
        log.info("采集的大盘数据: {}当前时间: {}",list,curTime);
        //this.stockMarketIndexInfoMapper.insertBatch(list);
    }

    @Override
    public void getStockRtIndex() {
        //获取所有股票的id TODO 缓存优化
       List<String> stockIds = stockBusinessMapper.findAllStockIds();
       //深圳lA:以0开头 上证: 6开头
        //用来结束stream()流,并for循环
        stockIds = stockIds.stream().map(id->{
            id = id.startsWith("6")?"sh"+id:"sz"+id;
            return id;
        }).collect(Collectors.toList());
        //要求:将集合分组,每组的集合长度为20一次性查询过多，我们将需要查询的数据先进行分片处理，每次最多查询20条股票数据
        //将list集合按指定长度进行切分，返回新的List<List<??>>集合 guva包提供的 因为数据太多所以分区
        Lists.partition(stockIds,20).forEach(ids->{
            //每个分片的数据开启一个线程异步执行任务
            threadPoolTaskExecutor.execute(()->{

            //拼接获取A股信息的url地址
           String stockRtUrl= stockInConfig.getMarketUrl()+ String.join(",",ids);
           //发送请求获取数据
            String result = restTemplate.getForObject(stockRtUrl,String.class);
            //解析获取股票数据
            String reg="var hq_str_(\\S*)=(.*);";
            Pattern pattern = Pattern.compile(reg);
            Matcher matcher = pattern.matcher(result);
            ArrayList<StockRtInfo> list = new ArrayList<>();
            while (matcher.find()) {
              //获取主要
                String stockCode = matcher.group(1).substring(2);
                //其他信息
                String other = matcher.group(2);
                String[] others=other.split(",");
                //大盘名称
                String stockName = others[0];
                //今日开盘价
                BigDecimal openPrice = new BigDecimal(others[1]);
                //昨日收盘价
                BigDecimal preClosePrice = new BigDecimal(others[2]);
                //当前价格
                BigDecimal currentPrice = new BigDecimal(others[3]);
                //今日最高价额
                BigDecimal maxPrice = new BigDecimal(others[4]);
                //今日最低价额
                BigDecimal minPrice = new BigDecimal(others[5]);
                //成交量
                Long tradeAmount = Long.valueOf(others[8]);
                //成交金额
                BigDecimal tradeVol = new BigDecimal(others[9]);
                //当前日期
              Date currentTime = DateTime.parse(others[30]+" "+others[31], DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")).toDate();

                StockRtInfo stockRtInfo = StockRtInfo.builder()
                        .id(idWorker.nextId())
                        .stockCode(stockCode)
                        .stockName(stockName)
                        .openPrice(openPrice)
                        .preClosePrice(preClosePrice)
                        .curPrice(currentPrice)
                        .maxPrice(maxPrice)
                        .minPrice(minPrice)
                        .tradeAmount(tradeAmount)
                        .tradeVolume(tradeVol)
                        .curTime(currentTime)
                        .build();
                    list.add(stockRtInfo);
            }
            log.info("集合长度: {}, 内容:{}",list.size(),list);
            //批量插入
            if(CollectionUtils.isEmpty(list)){
                log.info("");
                return;
            }

             //   this.stockRtInfoMapper.insertBatch(list);

//            //解析获取股票数据
//            List<StockRtInfo> list = parserStockInfoUtil.parser4StockOrMarketInfo(result, 3);
//            //分批次批量插入
//            stockRtInfoMapper.insertBatch(list);
            });
        });
    }
    /**
     * 获取国内的大盘的板块数据
     */
    @Override
    public void getStockSectorIndex() {
        //1.组装url地址
        String blockUrl=stockInConfig.getBlockUrl();
        //2.获取响应数据
        String result = restTemplate.getForObject(blockUrl, String.class);
        //3.调用解析工具类获取板块集合
        List<StockBlockRtInfo> infos = parserStockInfoUtil.parse4StockBlock(result);
        //4.分片处理
        Lists.partition(infos,20).forEach(items->{
            threadPoolTaskExecutor.execute(()->{
                log.info("当前模块: {}", items);

            //批量插入
          //  stockBlockRtInfoMapper.insertBatch(items);
            });
        });
        try {
            TimeUnit.MINUTES.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
